/*=========================================================================
This file is part of CustusX, an Image Guided Therapy Application.
                 
Copyright (c) SINTEF Department of Medical Technology.
All rights reserved.
                 
CustusX is released under a BSD 3-Clause license.
                 
See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
=========================================================================*/

#include <vtkPolyData.h>
#include <vtkPolyDataWriter.h>
#include <vtkCellArray.h>
#include "cxMesh.h"
#include "cxVector3D.h"
#include "cxDataLocations.h"
#include "vesselReg/SeansVesselReg.hxx"
#include "cxRegistrationTransform.h"
#include "cxTypeConversions.h"
#include <QFileInfo>
#include <QDir>
#include "cxXmlOptionItem.h"
#include "cxConfig.h"
#include "catch.hpp"

#include "cxTime.h"
#include "cxDataLocations.h"
#include "cxElastixExecuter.h"
#include "cxSettings.h"
#include "cxElastixSingleThreadedRunner.h"
#include "cxTypeConversions.h"
#include "cxElastixParameters.h"
#include "cxLogicManager.h"
#include "cxRegServices.h"

#include "cxReporter.h"

#include "cxtestPatientModelServiceMock.h"
#include "cxPatientModelServiceProxy.h"

namespace cxtest
{

/** 
 *
 *
 * \ingroup cx
 * \date 6/7/2013, 2013
 * \author christiana
 */

class ElastiXFixture
{
public:
	ElastiXFixture()
	{
		cx::Reporter::initialize();
	}

	~ElastiXFixture()
	{
		cx::Reporter::shutdown();
	}
	bool compareTransforms(cx::Transform3D result, cx::Transform3D solution)
	{
		std::cout << "result\n" << result << std::endl;
		std::cout << "solution\n" << solution << std::endl;

		cx::Transform3D diff = solution * result.inv();

		std::cout << "diff\n" << diff << std::endl;

		cx::Vector3D t_delta = diff.matrix().block<3, 1>(0, 3);
		Eigen::AngleAxisd angleAxis = Eigen::AngleAxisd(diff.matrix().block<3, 3>(0, 0));
		double angle = angleAxis.angle();

		cx::Vector3D shift = diff.coord(cx::Vector3D(0,0,0));


		QString res = QString(""
			"Shift vector (r):\t%1\n"
			"Accuracy |v|:\t%2mm\n"
			"Angle:       \t%3*\n"
			"")
			.arg(qstring_cast(shift))
			.arg(shift.length(), 6, 'f', 2)
			.arg(angle / M_PI * 180.0, 6, 'f', 2);

		std::cout << res << std::endl;

		return (fabs(angle/M_PI*180.0) < 0.1) && (shift.length() < 0.1);
	}
};


#ifdef CX_CUSTUS_SINTEF
TEST_CASE("ElastiX should register kaisa to a translated+resampled version of same", "[pluginRegistration][integration][not_win32][not_win64]")
{
	cx::LogicManager::initialize();
	cx::PatientModelServicePtr pasm = cx::PatientModelServiceProxy::create(cx::logicManager()->getPluginContext());

	ElastiXFixture fixture;

	QString kaisa_padded_fname = cx::DataLocations::getTestDataPath() + "/testing/elastiX/kaisa_padded.mhd";
	QString kaisa_resliced_fname = cx::DataLocations::getTestDataPath() + "/testing/elastiX/kaisa_resliced.mhd";
	QString kaisa_resliced_linear_fname = cx::DataLocations::getTestDataPath() + "/testing/elastiX/kaisa_resliced_linear.mhd";

//	std::cout << "------" << kaisa_padded_fname << std::endl;

	QString dummy;

	cx::DataPtr kaisa_resliced_linear = pasm->importData(kaisa_resliced_linear_fname, dummy);
	cx::DataPtr kaisa_padded = pasm->importData(kaisa_padded_fname, dummy);
	cx::DataPtr kaisa_resliced = pasm->importData(kaisa_resliced_fname, dummy);

	REQUIRE(kaisa_resliced_linear);
	REQUIRE(kaisa_padded);
	REQUIRE(kaisa_resliced);

	QString elastixPreset = "elastix/p_Rigid"; // this is an autogenerated preset

	cx::Transform3D solution;
	solution.matrix() <<
				1, 0 ,0, 10,
				0, 1, 0,  5,
				0, 0, 1, -2,
				0, 0, 0,  1;

	cx::Transform3D result = cx::Transform3D::Identity();

	cx::ElastixParametersPtr parameters(new cx::ElastixParameters(cx::XmlOptionFile()));
	parameters->getCurrentPreset()->setValue(elastixPreset);

	cx::RegServicesPtr services = cx::RegServices::create(cx::logicManager()->getPluginContext());

	cx::ElastixSingleThreadedRunner runner(services);
	REQUIRE(runner.registerLinear(kaisa_padded, kaisa_resliced_linear, parameters, &result));

	REQUIRE(fixture.compareTransforms(result, solution) == true);

	cx::LogicManager::shutdown();
}
#endif

} // namespace cxtest


